using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Design;
using Microsoft.CSharp;
using OpenComposite.EII.Designer.Workflow;
using System.Collections;
using OpenComposite.EII.Repository;
using OpenComposite.Base.Collections;

using Dom = ICSharpCode.SharpDevelop.Dom;
using NRefactory = ICSharpCode.NRefactory;
using Core.Controls.CSharpEditor;

namespace OpenComposite.EII.Forms
{
	public partial class FormCodeEditor : Form
	{
		public FormCodeEditor(IServiceProvider serviceProvider)
		{
			_serviceProvider = serviceProvider;

			InitializeComponent();

			syntaxCodeEditor.FooterText = Environment.NewLine + "}}}";

			//            dotNetProjectResolver.CachePath = Path.Combine(Path.GetTempPath(), "OpenComposite\\cache");
			//            dotNetProjectResolver.AddExternalReferenceForMSCorLib();
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System");
			//#if DEBUG
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Windows.Forms");
			//#endif
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Configuration");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Data");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Design");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Drawing");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Drawing.Design");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Transactions");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Web");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Xml");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Web.Services");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.ServiceModel");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Runtime.Serialization");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Workflow.ComponentModel");
			//            dotNetProjectResolver.AddExternalReferenceForSystemAssembly("System.Workflow.Activities");
			//            dotNetProjectResolver.AddExternalReference(typeof(OpenComposite.Workflow.LogicalCapabilityActivity).Assembly);
			//            dotNetProjectResolver.AddExternalReference(typeof(OpenComposite.Base.Helper).Assembly);
			//            dotNetProjectResolver.AddExternalReference(typeof(OpenComposite.Base.Structures.RepositoryInformationAttribute).Assembly);


			// Flush CS code
			WorkflowLoader wl = (WorkflowLoader)_serviceProvider.GetService(typeof(WorkflowDesignerLoader));
			CSharpCodeProvider provider = new CSharpCodeProvider();

			// Just chooses some formatting options, like four space indenting
			CodeGeneratorOptions options = new CodeGeneratorOptions();
			options.BlankLinesBetweenMembers = true;
			options.BracingStyle = "C";
			options.ElseOnClosing = true;
			options.IndentString = "\t";

			using ( StringWriter sw = new StringWriter() ) {
				provider.GenerateCodeFromCompileUnit(wl.CodeBesideCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.DataCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.ContractsCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.InterfaceCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.LocalServiceCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.LogicalActivitiesCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.MappingCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.RulesCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.ServicesCCU, sw, options);
				provider.GenerateCodeFromCompileUnit(wl.OrchestrationInterfaceCCU, sw, options);
				// uncomment this for extended code access
				//provider.GenerateCodeFromCompileUnit(wl.XamlCodeCompileUnit, sw, options);
				string s = sw.ToString();
				s = s.Replace(", " + wl.OrchestrationInterfaceName, "");
				ParseCode(s);
				//dotNetProjectResolver.SourceProjectContent.LoadForCode(cSharpSyntaxLanguage, "CodeEditor1.cs", s);

			}

			//            syntaxCodeEditor.Document.Filename = "mycode.cs";
			//            syntaxCodeEditor.Document.Language = cSharpSyntaxLanguage;
			//            syntaxCodeEditor.Document.LanguageData = dotNetProjectResolver;
			//            cSharpSyntaxLanguage.SyntaxEditorIntelliPromptMemberListPreFilter += new IntelliPromptMemberListPreFilterEventHandler(cSharpSyntaxLanguage_SyntaxEditorIntelliPromptMemberListPreFilter);

			//            syntaxCodeEditor.Document.Reparse();

			syntaxCodeEditor.SetHighlighting("C#");

			this.DialogResult = DialogResult.Cancel;
		}

		private Dom.ICompilationUnit ConvertCompilationUnit(NRefactory.Ast.CompilationUnit cu)
		{
			Dom.NRefactoryResolver.NRefactoryASTConvertVisitor converter;
			converter = new Dom.NRefactoryResolver.NRefactoryASTConvertVisitor(syntaxCodeEditor.ProjectContent);
			cu.AcceptVisitor(converter, null);
			return converter.Cu;
		}
		private void ParseCode(string code)
		{
			TextReader textReader = new StringReader(code);
			Dom.ICompilationUnit newCompilationUnit;
			NRefactory.SupportedLanguage supportedLanguage;
			if ( CodeEditorControl.IsVisualBasic )
				supportedLanguage = NRefactory.SupportedLanguage.VBNet;
			else
				supportedLanguage = NRefactory.SupportedLanguage.CSharp;
			using ( NRefactory.IParser p = NRefactory.ParserFactory.CreateParser(supportedLanguage, textReader) ) {
				// we only need to parse types and method definitions, no method bodies
				// so speed up the parser and make it more resistent to syntax
				// errors in methods
				p.ParseMethodBodies = false;

				p.Parse();
				newCompilationUnit = ConvertCompilationUnit(p.CompilationUnit);
			}
			// Remove information from lastCompilationUnit and add information from newCompilationUnit.
			syntaxCodeEditor.ProjectContent.UpdateCompilationUnit(lastCompilationUnit, newCompilationUnit, CodeEditorControl.DummyFileName);
			lastCompilationUnit = newCompilationUnit;
			parseInformation.SetCompilationUnit(newCompilationUnit);
		}
		internal Dom.ParseInformation parseInformation = new Dom.ParseInformation();
		private Dom.ICompilationUnit lastCompilationUnit;

		private string Usings
		{
			get
			{
				StringBuilder sb = new StringBuilder();
				sb.Append("namespace OpenComposite.Orchestration");
				sb.Append(".").Append(_className).AppendLine("{");
				sb.AppendLine("using System;");
				sb.AppendLine("using System.Xml;");
				sb.AppendLine("using System.Web.Services;");
				sb.AppendLine("using System.ServiceModel;");
				sb.AppendLine("using System.Runtime.Serialization;");
				sb.AppendLine("using System.Workflow.ComponentModel;");
				sb.AppendLine("using System.Workflow.Activities;");
				sb.AppendLine("using OpenComposite.Workflow;");
				sb.AppendLine("using OpenComposite.Base.Structures;");
				sb.AppendLine(string.Format("using OpenComposite.Orchestration.{0}.Data;", _className));
				return sb.ToString();
			}
		}

		private string _className;

		public void SetHeader(string methodname, string WorkflowClassName)
		{
			_className = WorkflowClassName;
			syntaxCodeEditor.HeaderText = Usings +
				"public partial class " + WorkflowClassName + Environment.NewLine +
				"{" + methodname + "{" + Environment.NewLine;
			lblMethodHeader.Text = methodname;
			//syntaxCodeEditor.Document.Reparse();
		}

		private IServiceProvider _serviceProvider;

		public string Code
		{
			get
			{
				//string tmp = syntaxCodeEditor.Document.HeaderText + syntaxCodeEditor.Document.Text + syntaxCodeEditor.Document.FooterText;
				return syntaxCodeEditor.FullText;
			}
			set
			{
				if ( value == null )
					value = "";
				syntaxCodeEditor.Text = value;
			}
		}
		public string MethodHeader
		{
			get { return lblMethodHeader.Text; }
		}

		public object[] Members
		{
			get
			{
				// return members for code completion
				return null;
			}
		}

		private void tsbtnOK_Click(object sender, EventArgs e)
		{
			this.DialogResult = DialogResult.OK;
			this.Close();
		}

		private void tsbtnCancel_Click(object sender, EventArgs e)
		{
			this.DialogResult = DialogResult.Cancel;
			this.Close();
		}

		//private void cSharpSyntaxLanguage_SyntaxEditorIntelliPromptMemberListPreFilter(object sender, IntelliPromptMemberListPreFilterEventArgs e)
		//{
		//    memberToSelect = null;
		//    itemToSelect = null;
		//    DotNetContext context = e.Context as DotNetContext;
		//    csContext = null;
		//    if ( context != null ) {
		//        if ( context.Type == DotNetContextType.NewObjectDeclaration ) {
		//            IToken token = syntaxCodeEditor.Document.Tokens.GetTokenAtOffset(context.TargetOffset);
		//            IToken prev = syntaxCodeEditor.Document.Tokens.GetTokenAtOffset(token.StartOffset - 1);
		//            while ( prev.ID != CSharpTokenID.Identifier && prev.StartOffset != 0 ) {
		//                prev = syntaxCodeEditor.Document.Tokens.GetTokenAtOffset(prev.StartOffset - 1);
		//            }
		//            string tokenText = syntaxCodeEditor.Document.GetTokenText(prev);
		//            csContext = CSharpContext.GetContextAtOffset(syntaxCodeEditor.Document,
		//                prev.StartOffset, context.CompilationUnit, dotNetProjectResolver);
		//            memberToSelect = csContext.TypeDeclarationNode.GetMember(null, tokenText, DomBindingFlags.Default);
		//        }
		//    }
		//    bool foundItem = false;
		//    List<object> keys = new List<object>();
		//    foreach ( DictionaryEntry item in e.Items ) {
		//        if ( ( (string)item.Key ).StartsWith("_") ) {
		//            keys.Add(item.Key);
		//        } else if ( !foundItem && memberToSelect != null ) {
		//            itemToSelect = item.Value as IntelliPromptMemberListItem;
		//            if ( memberToSelect != null && itemToSelect.Text == memberToSelect.Name ) {
		//                foundItem = true;
		//            }
		//        }
		//    }
		//    foreach ( object key in keys ) {
		//        e.Items.Remove(key);
		//    }
		//}

		//private void syntaxCodeEditor_IntelliPromptMemberListSelectedItemChanged(object sender, EventArgs e)
		//{
		//    if ( memberToSelect != null &&
		//        syntaxCodeEditor.IntelliPrompt.MemberList.SelectedItem != itemToSelect ) {
		//        syntaxCodeEditor.IntelliPrompt.MemberList.SelectedItem = itemToSelect;
		//    }
		//}

	}
}